package com.example.test001;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;

@Configuration
public class ThreadPoolConfig {

    @Bean(name = "customThreadPool")
    public ThreadPoolTaskExecutor  customThreadPool() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5); // 核心线程数
        executor.setMaxPoolSize(10); // 最大线程数
        executor.setQueueCapacity(25); // 队列容量
        executor.setThreadNamePrefix("custom-thread-"); // 线程前缀名称
        //重中之重，配置了这个，当线程数大于队列+最大线程数的时候，就不会报错了
//        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }

    @Bean("stockTaskExecutor")
    public ThreadPoolTaskExecutor stockTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5); // 核心线程数
        executor.setMaxPoolSize(10); // 最大线程数
        executor.setQueueCapacity(25); // 队列容量
        executor.setKeepAliveSeconds(60);//非核心线程存活时间
        executor.setThreadNamePrefix("stockTaskExecutor-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;

    }

    // 定义一个自定义的ThreadFactory
    class CustomThreadFactory implements ThreadFactory {
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final String namePrefix;

        // 构造函数，传入线程前缀
        public CustomThreadFactory(String namePrefix) {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
            this.namePrefix = namePrefix;
            System.out.println("CustomThreadFactory: group" + this.namePrefix);
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
            // 如果线程是守护线程，将其设置为非守护线程，以便它能阻止JVM退出
            if (t.isDaemon())
                t.setDaemon(false);
            // 如果线程优先级不正常，将其设置为默认优先级
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }

    // 配置线程池bean
    @Bean("stockTaskExecutor1")
    public ThreadPoolTaskExecutor stockTaskExecutor1() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5); // 核心线程数
        executor.setMaxPoolSize(10); // 最大线程数
        executor.setQueueCapacity(25); // 队列容量
        executor.setKeepAliveSeconds(60); // 非核心线程存活时间
        executor.setThreadNamePrefix("stockTaskExecutor-"); // 前缀

        // 使用自定义的ThreadFactory
        /**
         * 自定义ThreadFactory的作用在于提供对线程创建过程的控制，具体包括以下几个方面：
         * 线程命名：为线程指定一个有意义的名称，这在调试和监控时非常有用，因为线程名称可以帮助识别线程的用途和状态。
         * 线程优先级：设置线程的优先级，虽然在现代多核系统中，线程优先级的影响可能不如过去那么明显，但在某些情况下，它可以影响线程调度。
         * 线程属性：可以设置线程是否为守护线程（daemon thread），守护线程在所有非守护线程结束时自动结束，这对于后台服务或清理任务是有用的。
         * 线程初始化：可以在创建线程时执行一些初始化操作，例如设置线程局部变量、绑定数据或注册监听器等。
         * 资源管理：可以实现更精细的资源管理，例如限制线程的创建数量，或者在创建线程时记录相关信息。
         * 安全和隔离：在多租户环境中，每个线程可能需要有自己的安全上下文，自定义ThreadFactory可以确保每个线程都以正确的安全状态启动。
         * 跟踪和审计：在创建线程时记录日志，帮助追踪线程的创建和生命周期。
         */
        executor.setThreadFactory(new CustomThreadFactory(executor.getThreadNamePrefix()));

        // 拒绝策略：调用者运行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

        // 初始化线程池
        executor.initialize();
        return executor;
    }

}